package cn.ljy.authority.service.impl;

import cn.hutool.core.lang.ObjectId;
import cn.ljy.authority.config.security.TokenConfig;
import cn.ljy.authority.exception.model.MyVerifyCodeExpireException;
import cn.ljy.authority.model.dto.VerifyCodeDto;
import cn.ljy.authority.service.TokenService;
import cn.ljy.common.exception.model.MyWebException;
import cn.ljy.common.utils.file.Base64FileUtil;
import cn.ljy.common.utils.redis.StringRedisUtils;
import com.google.code.kaptcha.Producer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.awt.image.BufferedImage;
import java.util.concurrent.TimeUnit;

@Service
public class ITokenService implements TokenService {

    @Autowired
    private TokenConfig tokenConfig;
    @Autowired
    private StringRedisUtils stringRedisUtils;
    @Autowired
    private Producer producer;//验证码类

    /**
     * 获取用户对应的key
     * @param token
     * @return
     */
    private String getRedisKeyOfVerifyCodeToken(String token){
        return tokenConfig.getVerifyCodeTokenKeyHeader()+token;
    }

    @Override
    public VerifyCodeDto getVerifyCode() {
        //获取验证码生成的文本
        String virifyCode = producer.createText();
        //生成验证码图片
        BufferedImage image = producer.createImage(virifyCode);
        // 将验证码图片转换为base64类型的字符串
        String image64= Base64FileUtil.convertBufferedImageToString(image,"jpg");
        //获取客户端的token
        String token = this.getTokenAndSaveVerifyCode(null,virifyCode);
        //按规定格式返回
        VerifyCodeDto verifyCode = new VerifyCodeDto();
        verifyCode.setToken(token);
        verifyCode.setImg(image64);;
        verifyCode.setVirifyCode(virifyCode);//验证码，这里仅用于测试的时候自动填充验证码，正式运行时必须取消
        return verifyCode;
    }

    /**
     * 获取token并存储token和验证码到指定位置
     * 当前是存储于redis,默认有效期60秒
     * 说明：如果token不存在或
     * @param verifyCode 验证码
     * @return token
     */
    private String getTokenAndSaveVerifyCode(String token,String verifyCode){
        if(!StringUtils.hasLength(token)||!stringRedisUtils.exists(getRedisKeyOfVerifyCodeToken(token))) {//如果没有传递token,或是token已经不存在于redis中
            // 生成新的token
            token= ObjectId.next();
//            token = UUID.randomUUID().toString();
            // jwt生成的token太长，用来当key影响查询。改为相对短一点的uuid
            // token=JwtUtils.creatToken(claims,tokenConfig.getJwtSecret());
        }
        //将token存储到redis中,验证码的有效时间默认由配置文件决定
        stringRedisUtils.set(getRedisKeyOfVerifyCodeToken(token),verifyCode,tokenConfig.getVerifyCodeTokenExpireSeconds(), TimeUnit.SECONDS);
        return token;
    }



    @Override
    public void verifyVerifyCodeToken(String token,String verifyCode) {
        boolean judge=false;//默认验证失败
        if(!StringUtils.hasLength(verifyCode)){
            throw new MyWebException("请输入验证码");
        }else if(StringUtils.hasLength(token)){ // 如果token不为空
            //获取key加工后的值
            String key=this.getRedisKeyOfVerifyCodeToken(token);
            //检查redis是否包含有key
            if(stringRedisUtils.exists(key)) {//如果key还存在，即没有过期
               if(!verifyCode.equals(stringRedisUtils.get(key))){//如果验证码一致
                   throw new MyWebException("验证码错误");
               }
            }else{
                throw new MyVerifyCodeExpireException("验证码已经过期");
            }
        }else{
            throw new MyWebException("验证码的客户端非法");
        }
    }
}
